//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
// 
// You should have received a copy of the GNU Lesser General Public License
// along with this program.  If not, see http://www.gnu.org/licenses/.
// 

#include "CooperativeManager.h"

Define_Module(CooperativeManager);

CooperativeManager::CooperativeManager() {
    // TODO Auto-generated constructor stub

}

CooperativeManager::~CooperativeManager() {}

void CooperativeManager::initialize(int stage) {
    if(stage == 0) {

        brainIn = findGate("controlIn");
        brainOut = findGate("controlOut");

        updateIntervalTime = par("updateInterval");

        status_id = 0;

        db = check_and_cast<KnowledgeRepository *>(this->getParentModule()->getSubmodule("db"));
        manet = check_and_cast<ManetRoutingCallable *>(this->getParentModule()->getParentModule()->getSubmodule("manetrouting"));

        msgUpdate = new cMessage("updateMsg");
        scheduleAt(simTime() + fabs(normal(updateIntervalTime, 0.1)), msgUpdate);
    }
}

void CooperativeManager::handleMessage(cMessage *msg) {
    if (msg->isSelfMessage()) {
        handleSelfMsg(msg);
    }
    else if (msg->getArrivalGateId() == brainIn) {
        handleBrainMsg(msg);
    }
    else {
        error("Unknown message received: %s", msg->getFullName());
        delete(msg);
    }
}

void CooperativeManager::handleSelfMsg(cMessage *msg) {
    if(msg == msgUpdate) {
        updateOLSRmsg();

        scheduleAt(simTime() + fabs(normal(updateIntervalTime, 0.01)), msgUpdate);
    }
    else {
        error("Unknown self message received: %s", msg->getFullName());
        delete(msg);
    }
}


void CooperativeManager::handleBrainMsg(cMessage *msg) {
    delete(msg);
}

void CooperativeManager::finish() {
    cancelAndDelete(msgUpdate);
}

void CooperativeManager::updateOLSRmsg(void) {

    node_state_info_t my_info;
    std::list<node_state_info_t> neigh_list;

    //get node informations
    my_info.address = manet->getManetAddress();
    my_info.c_cell = db->getCongestionFactorCell();
    my_info.c_wifi = db->getCongestionFactorWifi();
    my_info.energy = db->getEnergyFactor();
    my_info.distance = db->getAverageGatewayDistance();
    my_info.role = db->getActualRule();
    my_info.nhopDistance = 0;
    my_info.msg_id = status_id++;

    //update OLSR informations
    manet->setMyPiggyBackInfo(&my_info);

    neigh_list.clear();
    db->getNeighbourhoodInfoList(neigh_list);

    //always reset before update
    manet->clearPiggyBackInfo();
    for (std::list<node_state_info_t>::iterator it = neigh_list.begin(); it != neigh_list.end(); it++) {
        node_state_info_t * infop= &(*it);
        manet->addNewPiggyBackInfo(infop);
    }
}

